package tcln.sors.client.base;

import java.util.Map;

import org.springframework.context.ApplicationContext;

import tcln.sors.client.SorsApplication;
import tcln.sors.client.core.mvc.ApplicationController;
import tcln.sors.client.core.mvc.BaseController;
import tcln.sors.client.core.mvc.ModelData;
import tcln.sors.service.core.EntityManagementService;
import tcln.sors.service.core.ManagementServiceFactory;

/**
 * @param <M>
 *            Model data type.
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public abstract class BaseSorsController<M extends ModelData<M>> extends BaseController<M> {

    /**
     * Single reference to the Spring application context.
     */
    private ApplicationContext beanApplicationContext;

    /**
     * Factory bean for {@link EntityManagementService}s.
     */
    private ManagementServiceFactory serviceFactory;

    /**
     * Initializes this controller base on given request parameters.
     * <p>
     * <b>Notes</b>:
     * <ul>
     * <li>This method is invoked only once when this controller is constructed by the application controller.
     * <li>This method is invoked by {@link ApplicationController} before this controller is ready for use.
     * <li>Usually, this method is used to build model data which is useful for display.
     * <li>On initializing this controller, the single Spring {@link ApplicationContext} reference is injected and
     * stored in {@link #beanApplicationContext}.
     * </ul>
     * <b>Caution</b>: When a subclass overrides this method, it's necessary that it call superclass implementation at
     * the first line to ensure dependency injection.
     * 
     * @param requestParameters
     */
    @Override
    public void initialize(Map<String, Object> requestParameters) {
        super.initialize(requestParameters);
        beanApplicationContext = SorsApplication.getAppInstance().getBeanContext();
        serviceFactory = beanApplicationContext.getBean("managementServiceFactory", ManagementServiceFactory.class);
    }

    /**
     * Returns current value of {@link #beanApplicationContext}.
     * 
     * @return the {@link #beanApplicationContext}.
     */
    protected ApplicationContext getBeanApplicationContext() {
        return beanApplicationContext;
    }

    /**
     * Returns current value of {@link #serviceFactory}.
     * 
     * @return the {@link #serviceFactory}.
     */
    protected ManagementServiceFactory getServiceFactory() {
        return serviceFactory;
    }
}
